﻿using System;

namespace _30_csharp_索引器
{
    class Program
    {
        static void Main(string[] args)
        {
            var p1 = new Person(5);
            #region 测试取值
            try
            {
                int index = 6;
                Console.WriteLine($"你要访问的第 {index + 1} 数据为 {p1[index]}");
            }
            catch (Exception e)
            {
                Console.WriteLine($"数据读取异常：{e}");
            }
            #endregion
            #region 测试赋值
            // 1. 正常范围的索引值
            Console.WriteLine($"Before = {p1}");
            p1[4] = 100;
            Console.WriteLine($"After = {p1}");
            // 2. 超范围的索引值赋值：
            // a 方案：直接拒绝操作，并提示超索引
            // b 方案： 扩容并赋值
            p1.needResize = true;
            p1[10] = 100;
            Console.WriteLine($"After = {p1}");


            #endregion

        }
    }


    class Person
    {
        // card ：卡片
        private int[] cards;
        public bool needResize;

        // 使用索引器来以数组的访问形式读取类类型实例中的数据（为对象建立索引）
        // 索引器的语法： 类型 this [索引] 
        // 索引器关键字套件： this（实例本身）、 get(得到值)、 set（设置值）、 value （被设置的值）
        // 索引器不必根据整数值类型进行索引，由你决定查找机制
        //  索引器可以被重载
        //  索引器可以有多个形参，如访问二维数组时

        public int this[int index]
        {
            get
            {
                if (index >= 0 && index < cards.Length)
                {
                    return cards[index];
                }
                else
                {
                    // throw : 抛出，丢出
                    // exception: 异常
                    // thorw exception:抛出一个异常，用于报告操作失败，一般需要 try 否则容易导致程序表现异常
                    throw new Exception("索引无效，我不知道给你回传个什么东西");
                }
            }
            set
            {
                if (index >= 0 && index < cards.Length)
                {
                    cards[index] = value;
                }
                else if (index >= cards.Length)
                {
                    // need 需要，resize 重新计算尺寸
                    if (needResize) // 如果需要扩容
                    {

                        ////1.  满打满算，创建一个新的数组
                        //int[] temp = new int[index + 1];
                        //// 2. 数据对拷
                        //for (int i = 0; i < cards.Length; i++)
                        //{
                        //    temp[i] = cards[i];
                        //}
                        //// 3. 把源数组替换为临时数组
                        //cards = temp;

                        Array.Resize(ref cards, index + 1);

                        // 4. 赋值
                        cards[index] = value;
                    }
                    else
                    {
                        Console.WriteLine($"数据填充失败，你的索引超了 {index} ，数据量为：{cards.Length}");
                    }
                }
                else
                {
                    Console.WriteLine($"你输入的索引为负数，请修正！");
                }
            }
        }

        public Person(int count)
        {
            cards = new int[count];
            for (int i = 0; i < count; i++)
            {
                cards[i] = i + 1;
            }
        }

        public void AddCard(int index, int card) { }


        public override string ToString()
        {
            // join : 参与，加入，把一个集合的每一项通过一个分隔符组合成一个字符串
            return string.Join(",", cards);// ctrl+shift+space
        }
    }

}
